#include <suif_copyright.h>
#include <stdio.h>
#include <simple.h>
#include "print.h"
#include "bitvector.h"
#include "cfg.h"


void print_sinstrs(simple_instr * sinstr) {
    simple_instr * current = sinstr;

    while(current) {
        fprint_instr(stdout, current);
        current = current->next;
    }
}

/*
prints the linked list of instruction
 used for debugging
*/
void print_instrs(instr_node * instr_head) {
	instr_node * i = instr_head;

	while(i) {
		printf("%3d", i->number);
		fprint_instr(stdout, i->instr);
		i = i->next;
	}
}

void print_blocks(basic_block_node * block_head) {
    basic_block_node * current_block = block_head;

    while(current_block) {
        instr_node * current_instr = current_block->start;

        printf("block # %d\n", current_block->number);
        while(current_instr && current_instr != current_block->end->next) {
            printf("%3d", current_instr->number);
            fprint_instr(stdout, current_instr->instr);
            current_instr = current_instr->next;
        }
        current_block = current_block->next;
    }
}

void print_cfg(basic_block_node * cfg_head, int total_blocks) {
	basic_block_node * current_block = cfg_head;
    instr_node * current_instr;
    block_ptr * predecessor_block;
    block_ptr * successor_block;
    
    // display rest of the blocks from the graph
    while(current_block) {
    	printf("\nblock %d\n", current_block->number);
    
    	current_instr = current_block->start;
    	printf("\tinstrs %d", current_block->total_instrs);
        while(current_instr != current_block->end)
        {
        	printf(" %d", current_instr->number);
            current_instr = current_instr->next;
        }
    
        if(current_block->start != NULL) {
            printf(" %d", current_instr->number);
        }
    
        printf("\n\tsuccessors %d", current_block->total_successors);
        successor_block = current_block->successor;
        while(successor_block) {
            printf(" %d", successor_block->block->number);
            successor_block = successor_block->next;
        }
    
        printf("\n\tpredecessors %d", current_block->total_predecessors);
        predecessor_block = current_block->predecessor;
        while(predecessor_block) {
            printf(" %d", predecessor_block->block->number);
            predecessor_block = predecessor_block->next;
        }
    
        current_block = current_block->next;
    }    
}

/*
	a print function to print the immediate dominators
*/
void print_idom(basic_block_node * cfg, char * proc_name, int maxblock) {
	basic_block_node * current_block = cfg;
    int exitidom = maxblock -2;
    int i = 0;
    
    printf("\nidominators %s %d", proc_name, maxblock);
    
    while(current_block) {
    	int index=0;
    
    	printf("\nblock %d\n", current_block->number);
        printf("\tidom");
    
        for(index = 0; index < maxblock; index++) {
    		if(get_bit(current_block->idom, index))
            {
    			printf(" %d", index);
            }
        }
    	current_block = current_block->next;
    }
}
    
/*
	a print function to print the dominators
*/
void print_dom(basic_block_node * cfg, int maxblock) {
	basic_block_node * current_block = cfg;
    
    while(current_block) {
    	int index = 0;
    	printf("\nblock %d > ", current_block->number);
    	for(index = 1; index < maxblock; index++) {
    		if(get_bit(current_block->dom, index))
    			printf(" %d", index);
    	}
   		current_block = current_block->next;
    }
}

// print natural loop function
void print_natural_loops(loop_block * loophead, int max_block_count) {
	loop_block * current_loop = loophead;
    block_ptr * tail = NULL;
    int loopcount = 0;
    int i = 0;
    
    while(current_loop) {
    	printf("natloop %d\n", loopcount++);
        printf("\tbackedge %d", current_loop->head->block->number);
        tail = current_loop->tail;
        while(tail) {
    		printf(" %d", tail->block->number);
            tail = tail->next;
       	}
        printf("\n\tpreheader %d", current_loop->head->block->number - 1);
        printf("\n\tloop_blocks");
        for( i = 0; i < max_block_count; i++)
    		if(get_bit(current_loop->nodes, i))
		       	printf(" %d", i);

		printf("\n");
        current_loop = current_loop->next;
	}
}

